﻿/********************************************************************
	created:	2011/05/13
	created:	13:5:2011   21:46
	filename: 	D:\My Documents\Visual Studio 2010\Projects\IntranetMessagerClient\Client\CreateDuplexChannel.cs
	file path:	D:\My Documents\Visual Studio 2010\Projects\IntranetMessagerClient\Client
	file base:	CreateDuplexChannel
	file ext:	cs
	author:		
	
	purpose:	为该客户端订制的创建双工通道的类
*********************************************************************/
using System;
using System.ComponentModel;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace Client
{
    internal class CreateDuplexChannel<TChannel> : INotifyPropertyChanged
    {
        private readonly Binding _binding;
        private readonly EndpointAddressBuilder _endpointAddressBuilder;
        private readonly InstanceContext _instanceContext;
        private DuplexChannelFactory<TChannel> _factory;
        private string _ip = String.Empty;

        public CreateDuplexChannel()
        {
            IpAddress = "localhost";
            _binding = new WSDualHttpBinding();
            _endpointAddressBuilder = new EndpointAddressBuilder();
            _instanceContext = new InstanceContext(new ClientCallback());
        }

        public CreateDuplexChannel(bool isTcp)
        {
            IpAddress = "localhost";
            IsTcp = isTcp;
            if (isTcp)
                _binding = new NetTcpBinding();
            else
                _binding = new WSDualHttpBinding();

            _endpointAddressBuilder = new EndpointAddressBuilder();
            _instanceContext = new InstanceContext(new ClientCallback());
        }

        public CreateDuplexChannel(bool isTcp, object implementation)
        {
            IpAddress = "localhost";
            IsTcp = isTcp;
            if (isTcp)
                _binding = new NetTcpBinding();
            else
                _binding = new WSDualHttpBinding();

            _endpointAddressBuilder = new EndpointAddressBuilder();
            _instanceContext = new InstanceContext(implementation);
        }

        public CreateDuplexChannel(bool isTcp, object implementation, string ip)
        {
            IsTcp = isTcp;
            IpAddress = ip;
            if (isTcp)
                _binding = new NetTcpBinding();
            else
                _binding = new WSDualHttpBinding();

            _endpointAddressBuilder = new EndpointAddressBuilder();
            _instanceContext = new InstanceContext(implementation);
        }

        public string IpAddress
        {
            get { return _ip; }
            set
            {
                _ip = value;
                OnPropertyChanged("IP");
            }
        }

        public bool IsTcp { get; private set; }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private void OnPropertyChanged(string propValue)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propValue));
        }

        internal TChannel CreateChannel()
        {
            _factory = new DuplexChannelFactory<TChannel>(_instanceContext, _binding, MakeEndpointAddress());
            return _factory.CreateChannel();
        }

        private EndpointAddress MakeEndpointAddress()
        {
            if (_ip == String.Empty)
                throw new ArgumentNullException(IpAddress);
            else
            {
                string ip = String.Format(IsTcp ? "net.tcp://{0}/" : "http://{0}:8732/Design_Time_Addresses/", _ip);
                _endpointAddressBuilder.Uri = new Uri(ip);
                return _endpointAddressBuilder.ToEndpointAddress();
            }
        }
    }
}